package com.winning.common.xmlSchema.schema;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.io.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.winning.common.Constans;
import com.winning.common.xmlSchema.ICDASchemaValidatorInter;
import com.winning.common.xmlSchema.SchemaSummary;

import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.*;
import java.util.HashMap;

/**
 * 类名称：CDASchemaSAXValidator
 * 类描述：卫生信息共享文档Schema校验接口实现类
 * 创建人：liuwensheng
 * 创建时间：2017-1-12 上午11:11:21
 * 修改人：liuwensheng
 * 修改时间：2017-1-12 上午11:11:21
 * 修改备注：
 */
public class CDASchemaSAXValidator implements ICDASchemaValidatorInter {

    private Logger logger = Logger.getLogger(CDASchemaSAXValidator.class);


    private static Logger LOGGER = Logger.getLogger(Constans.LOG4J_PBS_LOGGER_ID);

    private static CDASchemaSAXValidator cda_validator;
    private Schema schema = null;

    private CDASchemaSAXValidator(InputStream xsdInput) {

        SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
        factory.setResourceResolver(new SchemaURIResolver());
        try {
            schema = factory.newSchema(new SAXSource(new InputSource(xsdInput)));
        } catch (SAXException e) {
            e.printStackTrace();

        }
    }

    public static CDASchemaSAXValidator newInstance(InputStream xsdInput) throws FileNotFoundException {
        if (cda_validator == null) {
            cda_validator = new CDASchemaSAXValidator(xsdInput);
        }
        return cda_validator;
    }

    public HashMap<String, Object> validate(InputStream input) {

        SchemaErrorHandler errorHandler = new SchemaErrorHandler();

        HashMap<String, Object> result = new HashMap<String, Object>();

        try {
            LOGGER.info("-->进入文档验证-------------------------------------------");

            Validator validator = schema.newValidator();
            validator.setErrorHandler(errorHandler);


            //不知道为什么,虽然DocumentSource也是继承自SAXSource,
            //但是这里如果使用DocumentSource是捕获不到出错行号的.
            //必须使用SAXSource.
            //DocumentSource source = new DocumentSource(input);
            SAXSource source = new SAXSource(new InputSource(input));
            validator.validate(source);


            //验证有没有错误
            SchemaSummary summary = new SchemaSummary();
            summary.fromSchemaResultDocument(errorHandler.getReport());
            LOGGER.info("-->CDA文档错误详情：" + errorHandler.getReport().asXML());

            if (summary.getErrorCount() > 0) {
                result.put("YZJG", "AE");
                result.put("YZJGSM", "错误详情：" + errorHandler.getReport().asXML());
                LOGGER.info("-->共享文档格式验证失败!错误详情：" + errorHandler.getReport().asXML());

            } else {
                result.put("YZJG", "AA");
                result.put("YZJGSM", "共享文档格式验证成功");
                LOGGER.info("-->共享文档格式验证成功!");
            }

        } catch (SAXException ex) {
            result.put("YZJG", "AE");
            result.put("YZJGSM", "文档验证失败,因为:" + ex.fillInStackTrace().toString());
            LOGGER.info("-->文档验证失败,因为:SAX:" + ex.fillInStackTrace().toString());

        } catch (IOException e) {
            result.put("YZJG", "AE");
            result.put("YZJGSM", "文档验证失败,因为:" + e.fillInStackTrace().toString());
            LOGGER.info("-->文档验证失败,因为:IO:" + e.fillInStackTrace().toString());


        }

        LOGGER.info("-->结束文档验证-------------------------------------------");

        return result;
    }

    public static void main(String[] args) throws FileNotFoundException {

        SAXReader xsdreader = new SAXReader();
        FileInputStream xsdFile = null;
        xsdFile = new FileInputStream("G:/Test/PCHIS_CDA.xsd");

        InputStream input = null;
        try {
            input = new FileInputStream("G:/winning/WSCxfClient/src/com/cda.xml");

            //input = new FileInputStream("C:/Users/lenovo/Desktop/11、张家港测评/WSClient/src/config/CDA数据源/新生儿家庭访视_张芯悦.xml");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        CDASchemaSAXValidator validator = null;
        try {
            validator = CDASchemaSAXValidator.newInstance(xsdFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println(validator.validate(input).toString());

//        Document report = validator.validate(input);
//
//        OutputFormat format = OutputFormat.createPrettyPrint();
//        try {
//            XMLWriter writer = new XMLWriter(format);
//            writer.write(report);
//            writer.close();
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }


    public HashMap<String, Object> TestCDA(InputStream input) {

        SchemaErrorHandler errorHandler = new SchemaErrorHandler();

        HashMap<String, Object> result = new HashMap<String, Object>();

        try {

            Validator validator = schema.newValidator();
            validator.setErrorHandler(errorHandler);


            //不知道为什么,虽然DocumentSource也是继承自SAXSource,
            //但是这里如果使用DocumentSource是捕获不到出错行号的.
            //必须使用SAXSource.
            //DocumentSource source = new DocumentSource(input);
            SAXSource source = new SAXSource(new InputSource(input));
            validator.validate(source);


            //验证有没有错误
            SchemaSummary summary = new SchemaSummary();
            summary.fromSchemaResultDocument(errorHandler.getReport());
            LOGGER.info("-->CDA文档错误详情：" + errorHandler.getReport().asXML());

            if (summary.getErrorCount() > 0) {
                result.put("YZJG", "AE");
                result.put("YZJGSM", "错误详情：" + errorHandler.getReport().asXML());
                LOGGER.error("-->共享文档格式验证失败!错误详情：" + errorHandler.getReport().asXML());
            } else {
                result.put("YZJG", "AA");
                result.put("YZJGSM", "共享文档格式验证成功");
                LOGGER.info("-->共享文档格式验证成功!");
            }

        } catch (SAXException ex) {
            result.put("YZJGSM", "文档验证失败,因为:" + ex.fillInStackTrace().toString());
            LOGGER.info("-->文档验证失败,因为:SAX:" + ex.fillInStackTrace().toString());

        } catch (IOException e) {
            result.put("YZJGSM", "文档验证失败,因为:" + e.fillInStackTrace().toString());
            LOGGER.info("-->文档验证失败,因为:IO:" + e.fillInStackTrace().toString());


        }

        return result;
    }
}
